﻿using System;
using System.Collections.Generic;
using CoreVirtuoso;
using CoreVirtuoso.Config;
using CoreVirtuoso.Descriptions;
using CoreVirtuoso.Helpers;
using VDS.RDF.Query;
using VDS.RDF.Storage;
using VirtuosoDal.Config;
using VirtuosoDal.Entities;
using VirtuosoDal.Helpers;
using VirtuosoDal.Repositories.RdfRepositories.Interfaces.Events;

namespace VirtuosoDal.Repositories.RdfRepositories.Events
{
   public class EventsOntologyRepository : IEventsOntologyRepository
   {
      public Dictionary<string, EventPropertyDescription> GetAllEventPropertyDescriptions(string graphUri, string language)
      {
         string query = "prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> " +
                        "prefix owl:    <http://www.w3.org/2002/07/owl#> " +
                        "prefix  rdfs:     <http://www.w3.org/2000/01/rdf-schema#> " +
                        "prefix events:    <http://beaware.at/ontology#> " +
                        "SELECT DISTINCT ?property ?label ?isMultiValued ?isHierarchy ?hierarchyRoot ?isNotAutomatic ?isMultiline " +
                        "FROM @graph " +
                        "WHERE " +
                        "{ " +
                        " ?property rdf:type rdf:Property . " +
                        " ?property rdfs:label ?label . " +
                        " FILTER (lang(?label) = @lang) " +
                        " OPTIONAL " +
                        " { " +
                        " ?property events:isMultiValued ?isMultiValued . " +
                        " } " +
                        " OPTIONAL " +
                        " { " +
                        " ?property events:isHierarchy ?isHierarchy . " +
                        " ?property events:hierarchyRoot ?hierarchyRoot . " +
                        " } " +
                        " OPTIONAL " +
                        " { " +
                        " ?property events:isNotAutomatic ?isNotAutomatic . " +
                        " } " +
                        " OPTIONAL " +
                        " { " +
                        " ?property events:isMultiline ?isMultiline . " +
                        " } " +
                        "}";

         SparqlParameterizedString sparqlParameterizedString = new SparqlParameterizedString(query);
         sparqlParameterizedString.SetUri("@graph", new Uri(Namespaces.EventsOntologyNamespace));
         sparqlParameterizedString.SetLiteral("@lang", language);

         using (var virtuosoManager = new VirtuosoManager(ConnectionStringsHelper.GetVirtuosoConnectionString()))
         {
            SparqlResultSet sparqlResultSet = QueryHelper.Query(virtuosoManager,
                                                                sparqlParameterizedString.ToString(),
                                                                RuleSets.EventsRuleSet);

            return SparqlResultSetConverter.FromAllEventPropertyDescriptions(sparqlResultSet);
         }
      }

      public List<EntityDescription> GetChildClasses(string parentClassUri, string language)
      {
         string query = "prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> " +
                        "prefix owl:    <http://www.w3.org/2002/07/owl#> " +
                        "prefix  rdfs:     <http://www.w3.org/2000/01/rdf-schema#> " +
                        "prefix events:    <http://beaware.at/ontology#> " +
                        "SELECT DISTINCT ?child ?label " +
                        "FROM @graph " +
                        "WHERE " +
                        "{ " +
                        "?child rdfs:subClassOf @parent . " +
                        "?child rdfs:label ?label . " +
                        " FILTER (lang(?label) = @lang) " +
                        "} " +
                        "ORDER BY ?label";

         SparqlParameterizedString sparqlParameterizedString = new SparqlParameterizedString(query);
         sparqlParameterizedString.SetUri("@graph", new Uri(Namespaces.EventsOntologyNamespace));
         sparqlParameterizedString.SetUri("@parent", new Uri(parentClassUri));
         sparqlParameterizedString.SetLiteral("@lang", language);

         using (var virtuosoManager = new VirtuosoManager(ConnectionStringsHelper.GetVirtuosoConnectionString()))
         {
            SparqlResultSet sparqlResultSet = QueryHelper.Query(virtuosoManager,
                                                                sparqlParameterizedString.ToString(),
                                                                null);

            List<EntityDescription> childClasses = SparqlResultSetConverter.ToListOfEntityDescription(sparqlResultSet);

            return childClasses;
         }
      }
   }
}